﻿using System;
using System.Collections;
using System.Collections.Generic;
//using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using FFmpegVideoClip;
using FFmpegVideoClip.Lib;
using FFmpegVideoClip.Lib.TaskFlowProcessor;

namespace UtilityToolsCollect.ObjectsLibrary.TaskFlowProcessor
{
    public class TaskFlowProcessor : IList<TaskFlowAbstract>
    {
        private IEnumerable<Clip> clips;
        private List<TaskFlowAbstract> Tasks = new();
        public bool IsExecute { get; private set; }

        public TaskFlowProcessor() { clips = ClipManage.ClipList; }
        public TaskFlowProcessor(IEnumerable<Clip> clips) { this.clips = clips; }
        
        public int Execute(params object[] args)
        {
            ClipManage.ClipListCreateFragmentIndex();
            IsExecute = true;
            TaskFlowAbstract? Previous = null;
            Tools.CurrentCancelToken = new CancellationTokenSource();
            try
            {
                foreach (TaskFlowAbstract task in Tasks)
                {
                    if (Tools.IsCancellationRequested)
                        break;
                    if (Previous == null)
                        task.Execute(Tasks, null, args);
                    else
                        task.Execute(Tasks, Previous, args);
                    Previous = task;
                }
            }
            //catch (OperationCanceledException) { }
            catch (Exception exc)
            {
                LogManage.WriteExceptionInfo($"[{nameof(TaskFlowProcessor)}] 异常：", exc, true);
            }
            finally 
            {
                IsExecute = false;
                Tools.CurrentCancelToken.Dispose();
                Tools.CurrentCancelToken = null;
            }
            return 0;
        }
        public async Task<int> ExecuteAsync(params object[] args)
        {
           return await Task.Run(()=>Execute(args));
        }

        public TaskFlowAbstract this[int index] { get => ((IList<TaskFlowAbstract>)Tasks)[index]; set => ((IList<TaskFlowAbstract>)Tasks)[index] = value; }

        public int Count => ((ICollection<TaskFlowAbstract>)Tasks).Count;

        public bool IsReadOnly => ((ICollection<TaskFlowAbstract>)Tasks).IsReadOnly;

        public void Add(TaskFlowAbstract item)
        {
            CheckListChange();
            item.clips = clips;
            ((ICollection<TaskFlowAbstract>)Tasks).Add(item);
        }

        public void Clear()
        {
            CheckListChange();
            ((ICollection<TaskFlowAbstract>)Tasks).Clear();
        }

        public bool Contains(TaskFlowAbstract item)
        {
            return ((ICollection<TaskFlowAbstract>)Tasks).Contains(item);
        }

        public void CopyTo(TaskFlowAbstract[] array, int arrayIndex)
        {
            ((ICollection<TaskFlowAbstract>)Tasks).CopyTo(array, arrayIndex);
        }

        public IEnumerator<TaskFlowAbstract> GetEnumerator()
        {
            return ((IEnumerable<TaskFlowAbstract>)Tasks).GetEnumerator();
        }

        public int IndexOf(TaskFlowAbstract item)
        {
            return ((IList<TaskFlowAbstract>)Tasks).IndexOf(item);
        }

        public void Insert(int index, TaskFlowAbstract item)
        {
            CheckListChange();
            ((IList<TaskFlowAbstract>)Tasks).Insert(index, item);
        }

        public bool Remove(TaskFlowAbstract item)
        {
            CheckListChange();
            return ((ICollection<TaskFlowAbstract>)Tasks).Remove(item);
        }

        public void RemoveAt(int index)
        {
            CheckListChange();
            ((IList<TaskFlowAbstract>)Tasks).RemoveAt(index);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return ((IEnumerable)Tasks).GetEnumerator();
        }


        private void CheckListChange()
        {
            if(IsExecute)
                throw new TaskFlowProcessorListChangeException();
        }

        [Serializable]
        public class TaskFlowProcessorListChangeException : Exception
        {
            private const string message = "执行过程中进制操作队列数据";
            public TaskFlowProcessorListChangeException() : base(message) { }
            public TaskFlowProcessorListChangeException(Exception inner) : base(message, inner) { }
            [Obsolete] protected TaskFlowProcessorListChangeException(
              System.Runtime.Serialization.SerializationInfo info,
              System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
        }
    }
}
